﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using LDSBusiness;
using LDSBusiness.EventArgs;
using LDSCore;
using LDSModel.Dal;
using LDSModel.Item;

namespace LDSProject.Forms
{
    public partial class CmdProcessForm : Form
    {
        readonly List<int> _destAddressList;
        readonly string _title;
        readonly MsgType _msgType;
        int _processCount;
        readonly int _addressCount;
        readonly int _timeOut;
        OpType _type = OpType.QueryInfo;
        readonly StringBuilder _returnInfo;
        int _poIndex;
        bool _exitSendMessage;
        bool _flag;

        public CmdProcessForm(List<int> addressList, MsgType msgType, string title, ref StringBuilder returnInfo)
        {
            InitializeComponent();

            _destAddressList = addressList;
            _msgType = msgType;
            _timeOut = Properties.Settings.Default.CmdTimeOut;
            _returnInfo = returnInfo;
            _addressCount = addressList.Count;

            _title = (title ?? msgType.Description());
            lbTitle.Text = _title + lbTitle.Text;
            returnInfo.Append(_title);
            _flag = true;
        }

        private void CmdProcessForm_Load(object sender, EventArgs e)
        {
            DataRecipient.Instance.OnMsgProcess += Instance_OnMsgProcess;
            timer1.Start();
        }

        void SendMsg(object state)
        {
            List<int> addressList;
            lock (_destAddressList)
            {
                addressList = new List<int>(_destAddressList);
            }

            foreach (var address in addressList)
            {
                if (_exitSendMessage)
                {
                    _exitSendMessage = false;
                    return;
                }

                switch (_msgType)
                {
                    case MsgType.ZGCMD_READ_SYSINFO:
                        {
                            DataSender.Instance.ReadSysInfo(address);
                        }
                        break;
                    case MsgType.ZGCMD_READ_SYSTIME:
                        {
                            DataSender.Instance.ReadSysTime(address);
                        }
                        break;
                    case MsgType.ZGCMD_RESET:
                        {
                            DataSender.Instance.Reset(address);
                            _type = OpType.SetConfig;
                        }
                        break;
                    case MsgType.ZGCMD_DEFAULT:
                        {
                            DataSender.Instance.Restore(address);
                            _type = OpType.SetConfig;
                        }
                        break;
                    case MsgType.ZGCMD_SET_SYSTIME:
                        {
                            DataSender.Instance.SetSysTime(address);
#if _TRACE
                            Console.WriteLine(string.Format("请求同步时间： 线程Id({0}),发送地址({1})),时间({2})", Thread.CurrentThread.ManagedThreadId, address, DateTime.Now));
#endif
                            _type = OpType.SetConfig;
                        }
                        break;
                    case MsgType.ZGCMD_SYSTEM_CONFIG:
                        {
                            DataSender.Instance.Restore(address);
                            _type = OpType.SetConfig;
                        }
                        break;
                }

                Thread.Sleep(1000);
            }
        }


        void timer1_Tick(object sender, EventArgs e)
        {
            int count;

            lock (_destAddressList)
            {
                count = _destAddressList.Count;
            }

            if (count == 0) return;
            timer1.Interval = 30000;

            if (_processCount++ < _timeOut)
            {
                ThreadExecutor.Execute(SendMsg);
            }
            else
            {
                _exitSendMessage = true;

                timer1.Stop();

                if (_addressCount > _destAddressList.Count)
                {
                    lb.ForeColor = Color.Red;
                    lb.Left = lbInfo.Left;
                    lb.Top = lbInfo.Bottom + 5;
                    Controls.Add(lb);
                    var lbIndex = 0;

                    foreach (var text in _destAddressList.Select(address => (DeviceService.Instance.GetDeviceNameByAddress(address) + " 指令执行超时.")))
                    {
                        lb.Text += text;

                        MainConsole.Instance.SetErrorInfo(text, ref _flag);

                        if (lbIndex++ % 2 == 1)
                            lb.Text += "\r\n";
                        else
                            lb.Text += @"    ";
                    }
                    lbTitle.Text = _title + @"指令执行完成";
                }
                else
                {
                    lbTitle.Text = string.Format("{0}指令执行超时", _title);
                }
                btnCancel.Visible = true;
            }
        }

        void Instance_OnMsgProcess(object sender, MsgProcessEventArgs args)
        {
            if (_exitSendMessage) return;

            try
            {

#if _TRACE
                Console.WriteLine(string.Format("指令返回： 线程Id({0}),发送地址({1})),数据{2},时间({3})", Thread.CurrentThread.ManagedThreadId, args.Msg.DestAddr, JsonConvert.SerializeObject(args), DateTime.Now));
#endif

                MsgItem msg = args.Msg;

                if ((MsgType)msg.MsgType == MsgType.ZGCMD_ANSWER_OK ||
                    (MsgType)msg.MsgType == MsgType.ZGCMD_ANSWER_ERROR ||
                    (MsgType)msg.MsgType == MsgType.ZGCMD_SEND_SYSINFO ||
                    (MsgType)msg.MsgType == MsgType.ZGCMD_SEND_SYSTIME)
                {
                    lock (_destAddressList)
                    {
                        if (!_destAddressList.Contains(msg.SrcAddr)) return;

                        _destAddressList.Remove(msg.SrcAddr);
                    }
                }
                else
                {
                    return;
                }

                switch ((MsgType)msg.MsgType)
                {
                    case MsgType.ZGCMD_ANSWER_OK:
                        {
                            switch ((MsgType)msg.Exception)
                            {
                                case MsgType.ZGCMD_SET_SYSTIME:
                                    Invoke(new DelegateSetInfo(SetInfo), DeviceService.Instance.GetDeviceNameByAddress(msg.SrcAddr) + " 同步时间成功.", true);
                                    LogService.OperationLog(_type, UserService.CurrentUser.UserId, DeviceService.Instance.GetDeviceNameByAddress(msg.SrcAddr) + " 同步时间成功.");
                                    break;
                                case MsgType.ZGCMD_RESET:
                                    Invoke(new DelegateSetInfo(SetInfo), DeviceService.Instance.GetDeviceNameByAddress(msg.SrcAddr) + " 系统复位成功.", true);
                                    LogService.OperationLog(_type, UserService.CurrentUser.UserId, DeviceService.Instance.GetDeviceNameByAddress(msg.SrcAddr) + " 系统复位成功.");
                                    break;
                                case MsgType.ZGCMD_DEFAULT:
                                    Invoke(new DelegateSetInfo(SetInfo), DeviceService.Instance.GetDeviceNameByAddress(msg.SrcAddr) + " 恢复出厂值成功.", true);
                                    LogService.OperationLog(_type, UserService.CurrentUser.UserId, DeviceService.Instance.GetDeviceNameByAddress(msg.SrcAddr) + " 恢复出厂值成功.");
                                    break;
                            }
                        }
                        break;
                    case MsgType.ZGCMD_ANSWER_ERROR:
                        {
                            switch ((MsgType)msg.Exception)
                            {
                                case MsgType.ZGCMD_SET_SYSTIME:
                                    Invoke(new DelegateSetInfo(SetInfo), DeviceService.Instance.GetDeviceNameByAddress(msg.SrcAddr) + " 同步时间失败.", false);
                                    LogService.OperationLog(_type, UserService.CurrentUser.UserId, DeviceService.Instance.GetDeviceNameByAddress(msg.SrcAddr) + " 同步时间失败.");
                                    break;
                                case MsgType.ZGCMD_RESET:
                                    Invoke(new DelegateSetInfo(SetInfo), DeviceService.Instance.GetDeviceNameByAddress(msg.SrcAddr) + " 系统复位失败.", false);
                                    LogService.OperationLog(_type, UserService.CurrentUser.UserId, DeviceService.Instance.GetDeviceNameByAddress(msg.SrcAddr) + " 同步时间失败.");
                                    break;
                                case MsgType.ZGCMD_DEFAULT:
                                    Invoke(new DelegateSetInfo(SetInfo), DeviceService.Instance.GetDeviceNameByAddress(msg.SrcAddr) + " 恢复出厂值失败.", false);
                                    LogService.OperationLog(_type, UserService.CurrentUser.UserId, DeviceService.Instance.GetDeviceNameByAddress(msg.SrcAddr) + " 恢复出厂值失败.");
                                    break;
                            }
                        }
                        break;

                    #region 接收系统信息
                    case MsgType.ZGCMD_SEND_SYSINFO:
                        {
                            SysInfoItem info = null;
                            info = info.FromBytes<SysInfoItem>(msg.Buffer);
                            _returnInfo.Clear();
                            _returnInfo.Append("收到 " + DeviceService.Instance.GetDeviceNameByAddress(msg.SrcAddr) + " 配置信息:\t\t ");
                            _returnInfo.Append("\r\nID：" + info.ID);
                            _returnInfo.Append("\r\n型号：" + info.Name);
                            _returnInfo.Append("  版本：" + info.PrimaryVer.ToString(CultureInfo.InvariantCulture) + "." + info.AuxVer.ToString(CultureInfo.InvariantCulture));
                            //returnInfo.Append("\r\n出厂日期：" + info.ProductionDate.Date.ToShortDateString());
                            string date = Properties.Settings.Default.OutDate;
                            if (string.IsNullOrWhiteSpace(date)) date = info.ProductionDate.Date.ToShortDateString();
                            _returnInfo.Append("\r\n出厂日期：" + date);
                            _returnInfo.Append("\r\n本机地址：" + info.LocalAddr.ToString("000000"));
                            _returnInfo.Append("  目标地址：" + info.DestAddr.ToString("000000"));
                            //sb.Append("基站地址：" + info.BaseStationAddr.ToString() + Environment.NewLine);
                            //sb.Append("是否基站：" + (info.IsBaseStation ? "是" : "否"));

                            LogService.OperationLog(_type, UserService.CurrentUser.UserId, string.Format("查询({0})系统信息", msg.SrcAddr));

                            if (!IsDisposed)
                                Invoke(new DelegateEmpty(CmdSucess));
                        }
                        break;
                    #endregion

                    #region 接收系统时间
                    case MsgType.ZGCMD_SEND_SYSTIME:
                        {
                            RtcDateTime time = null;
                            time = time.FromBytes<RtcDateTime>(msg.Buffer);
                            _returnInfo.Clear();
                            _returnInfo.Append("收到 " + DeviceService.Instance.GetDeviceNameByAddress(msg.SrcAddr) + " 时间:");
                            _returnInfo.Append(time.ToSystemTime().ToString("yyyy-MM-dd HH:mm:ss"));
                            LogService.OperationLog(_type, UserService.CurrentUser.UserId, string.Format("查询({0})系统时间", msg.SrcAddr));
                            if (!IsDisposed)
                                Invoke(new DelegateEmpty(CmdSucess));
                        }
                        break;
                    #endregion
                }
            }
            catch (Exception ex)
            {
                LogFileHelper.Record(ex);
            }
        }

        public void SetInfo(string info, bool isok)
        {
            lbInfo.ForeColor = isok ? Color.Green : Color.Red;
            lbInfo.Text += info;

            if (_poIndex++ % 2 == 1)
            {
                lbInfo.Text += "\r\n";
                lb.Top = lbInfo.Bottom + 5;
            }
            else
                lbInfo.Text += @"    ";

            int count;

            lock (_destAddressList)
            {
                count = _destAddressList.Count;
            }

            if (count == 0)
            {
                lbTitle.Text = _title + @"指令执行完成";
                _exitSendMessage = true;
            }
            btnCancel.Visible = true;

            if (!isok)
            {
                MainConsole.Instance.SetErrorInfo(info, ref _flag);
            }
        }

        public void CmdSucess()
        {
            DialogResult = DialogResult.OK;
        }

        private void CmdProcessForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            timer1.Stop();
            _exitSendMessage = true;
            DataRecipient.Instance.OnMsgProcess -= Instance_OnMsgProcess;
        }
    }
}
